﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.Rendering.CullingResults
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Bindings;

#nullable disable
namespace UnityEngine.Rendering
{
  /// <summary>
  ///   <para>A struct containing the results of a culling operation.</para>
  /// </summary>
  [NativeHeader("Runtime/Export/RenderPipeline/ScriptableRenderPipeline.bindings.h")]
  [NativeHeader("Runtime/Scripting/ScriptingCommonStructDefinitions.h")]
  [NativeHeader("Runtime/Graphics/ScriptableRenderLoop/ScriptableCulling.h")]
  public struct CullingResults : IEquatable<CullingResults>
  {
    internal IntPtr ptr;
    private unsafe CullingAllocationInfo* m_AllocationInfo;
    private AtomicSafetyHandle m_Safety;

    [FreeFunction("ScriptableRenderPipeline_Bindings::GetLightIndexCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern int GetLightIndexCount(IntPtr cullingResultsPtr);

    [FreeFunction("ScriptableRenderPipeline_Bindings::GetReflectionProbeIndexCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern int GetReflectionProbeIndexCount(IntPtr cullingResultsPtr);

    [FreeFunction("FillLightAndReflectionProbeIndices")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void FillLightAndReflectionProbeIndices(
      IntPtr cullingResultsPtr,
      ComputeBuffer computeBuffer);

    [FreeFunction("FillLightAndReflectionProbeIndices")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void FillLightAndReflectionProbeIndicesGraphicsBuffer(
      IntPtr cullingResultsPtr,
      GraphicsBuffer buffer);

    [FreeFunction("GetLightIndexMapSize")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern int GetLightIndexMapSize(IntPtr cullingResultsPtr);

    [FreeFunction("GetReflectionProbeIndexMapSize")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern int GetReflectionProbeIndexMapSize(IntPtr cullingResultsPtr);

    [FreeFunction("FillLightIndexMapScriptable")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void FillLightIndexMap(
      IntPtr cullingResultsPtr,
      IntPtr indexMapPtr,
      int indexMapSize);

    [FreeFunction("FillReflectionProbeIndexMapScriptable")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void FillReflectionProbeIndexMap(
      IntPtr cullingResultsPtr,
      IntPtr indexMapPtr,
      int indexMapSize);

    [FreeFunction("SetLightIndexMapScriptable")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void SetLightIndexMap(
      IntPtr cullingResultsPtr,
      IntPtr indexMapPtr,
      int indexMapSize);

    [FreeFunction("SetReflectionProbeIndexMapScriptable")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void SetReflectionProbeIndexMap(
      IntPtr cullingResultsPtr,
      IntPtr indexMapPtr,
      int indexMapSize);

    [FreeFunction("ScriptableRenderPipeline_Bindings::GetShadowCasterBounds")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool GetShadowCasterBounds(
      IntPtr cullingResultsPtr,
      int lightIndex,
      out Bounds bounds);

    [FreeFunction("ScriptableRenderPipeline_Bindings::ComputeSpotShadowMatricesAndCullingPrimitives")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool ComputeSpotShadowMatricesAndCullingPrimitives(
      IntPtr cullingResultsPtr,
      int activeLightIndex,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData);

    [FreeFunction("ScriptableRenderPipeline_Bindings::ComputePointShadowMatricesAndCullingPrimitives")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool ComputePointShadowMatricesAndCullingPrimitives(
      IntPtr cullingResultsPtr,
      int activeLightIndex,
      CubemapFace cubemapFace,
      float fovBias,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData);

    [FreeFunction("ScriptableRenderPipeline_Bindings::ComputeDirectionalShadowMatricesAndCullingPrimitives")]
    private static bool ComputeDirectionalShadowMatricesAndCullingPrimitives(
      IntPtr cullingResultsPtr,
      int activeLightIndex,
      int splitIndex,
      int splitCount,
      Vector3 splitRatio,
      int shadowResolution,
      float shadowNearPlaneOffset,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData)
    {
      return CullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives_Injected(cullingResultsPtr, activeLightIndex, splitIndex, splitCount, ref splitRatio, shadowResolution, shadowNearPlaneOffset, out viewMatrix, out projMatrix, out shadowSplitData);
    }

    /// <summary>
    ///   <para>Array of visible lights.</para>
    /// </summary>
    public unsafe NativeArray<VisibleLight> visibleLights
    {
      get
      {
        return this.GetNativeArray<VisibleLight>((void*) this.m_AllocationInfo->visibleLightsPtr, this.m_AllocationInfo->visibleLightCount);
      }
    }

    /// <summary>
    ///   <para>Off-screen lights that still affect visible vertices.</para>
    /// </summary>
    public unsafe NativeArray<VisibleLight> visibleOffscreenVertexLights
    {
      get
      {
        return this.GetNativeArray<VisibleLight>((void*) this.m_AllocationInfo->visibleOffscreenVertexLightsPtr, this.m_AllocationInfo->visibleOffscreenVertexLightCount);
      }
    }

    /// <summary>
    ///   <para>Array of visible reflection probes.</para>
    /// </summary>
    public unsafe NativeArray<VisibleReflectionProbe> visibleReflectionProbes
    {
      get
      {
        return this.GetNativeArray<VisibleReflectionProbe>((void*) this.m_AllocationInfo->visibleReflectionProbesPtr, this.m_AllocationInfo->visibleReflectionProbeCount);
      }
    }

    private unsafe NativeArray<T> GetNativeArray<T>(void* dataPointer, int length) where T : struct
    {
      NativeArray<T> nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<T>(dataPointer, length, Allocator.Invalid);
      NativeArrayUnsafeUtility.SetAtomicSafetyHandle<T>(ref nativeArray, this.m_Safety);
      return nativeArray;
    }

    /// <summary>
    ///   <para>Gets the number of per-object light indices.</para>
    /// </summary>
    /// <returns>
    ///   <para>The number of per-object light indices.</para>
    /// </returns>
    public int lightIndexCount
    {
      get
      {
        this.Validate();
        return CullingResults.GetLightIndexCount(this.ptr);
      }
    }

    /// <summary>
    ///   <para>Gets the number of per-object reflection probe indices.</para>
    /// </summary>
    /// <returns>
    ///   <para>The number of per-object reflection probe indices.</para>
    /// </returns>
    public int reflectionProbeIndexCount
    {
      get
      {
        this.Validate();
        return CullingResults.GetReflectionProbeIndexCount(this.ptr);
      }
    }

    /// <summary>
    ///   <para>Gets the number of per-object light and reflection probe indices.</para>
    /// </summary>
    /// <returns>
    ///   <para>The number of per-object light and reflection probe indices.</para>
    /// </returns>
    public int lightAndReflectionProbeIndexCount
    {
      get
      {
        this.Validate();
        return CullingResults.GetLightIndexCount(this.ptr) + CullingResults.GetReflectionProbeIndexCount(this.ptr);
      }
    }

    /// <summary>
    ///   <para>Fills a buffer with per-object light indices.</para>
    /// </summary>
    /// <param name="computeBuffer">The compute buffer object to fill.</param>
    /// <param name="buffer">The buffer object to fill.</param>
    public void FillLightAndReflectionProbeIndices(ComputeBuffer computeBuffer)
    {
      this.Validate();
      CullingResults.FillLightAndReflectionProbeIndices(this.ptr, computeBuffer);
    }

    /// <summary>
    ///   <para>Fills a buffer with per-object light indices.</para>
    /// </summary>
    /// <param name="computeBuffer">The compute buffer object to fill.</param>
    /// <param name="buffer">The buffer object to fill.</param>
    public void FillLightAndReflectionProbeIndices(GraphicsBuffer buffer)
    {
      this.Validate();
      CullingResults.FillLightAndReflectionProbeIndicesGraphicsBuffer(this.ptr, buffer);
    }

    /// <summary>
    ///   <para>If a RenderPipeline sorts or otherwise modifies the VisibleLight list, an index remap will be necessary to properly make use of per-object light lists.</para>
    /// </summary>
    /// <param name="allocator">The allocator to use.</param>
    /// <returns>
    ///   <para>Array of indices that map from VisibleLight indices to internal per-object light list indices.</para>
    /// </returns>
    public unsafe NativeArray<int> GetLightIndexMap(Allocator allocator)
    {
      this.Validate();
      int lightIndexMapSize = CullingResults.GetLightIndexMapSize(this.ptr);
      NativeArray<int> nativeArray = new NativeArray<int>(lightIndexMapSize, allocator, NativeArrayOptions.UninitializedMemory);
      CullingResults.FillLightIndexMap(this.ptr, (IntPtr) nativeArray.GetUnsafePtr<int>(), lightIndexMapSize);
      return nativeArray;
    }

    public unsafe void SetLightIndexMap(NativeArray<int> lightIndexMap)
    {
      this.Validate();
      CullingResults.SetLightIndexMap(this.ptr, (IntPtr) lightIndexMap.GetUnsafeReadOnlyPtr<int>(), lightIndexMap.Length);
    }

    /// <summary>
    ///   <para>If a RenderPipeline sorts or otherwise modifies the VisibleReflectionProbe list, an index remap will be necessary to properly make use of per-object reflection probe lists.</para>
    /// </summary>
    /// <param name="allocator">The allocator to use.</param>
    /// <returns>
    ///   <para>Array of indices that map from VisibleReflectionProbe indices to internal per-object reflection probe list indices.</para>
    /// </returns>
    public unsafe NativeArray<int> GetReflectionProbeIndexMap(Allocator allocator)
    {
      this.Validate();
      int probeIndexMapSize = CullingResults.GetReflectionProbeIndexMapSize(this.ptr);
      NativeArray<int> nativeArray = new NativeArray<int>(probeIndexMapSize, allocator, NativeArrayOptions.UninitializedMemory);
      CullingResults.FillReflectionProbeIndexMap(this.ptr, (IntPtr) nativeArray.GetUnsafePtr<int>(), probeIndexMapSize);
      return nativeArray;
    }

    public unsafe void SetReflectionProbeIndexMap(NativeArray<int> lightIndexMap)
    {
      this.Validate();
      CullingResults.SetReflectionProbeIndexMap(this.ptr, (IntPtr) lightIndexMap.GetUnsafeReadOnlyPtr<int>(), lightIndexMap.Length);
    }

    public bool GetShadowCasterBounds(int lightIndex, out Bounds outBounds)
    {
      this.Validate();
      return CullingResults.GetShadowCasterBounds(this.ptr, lightIndex, out outBounds);
    }

    public bool ComputeSpotShadowMatricesAndCullingPrimitives(
      int activeLightIndex,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData)
    {
      this.Validate();
      return CullingResults.ComputeSpotShadowMatricesAndCullingPrimitives(this.ptr, activeLightIndex, out viewMatrix, out projMatrix, out shadowSplitData);
    }

    public bool ComputePointShadowMatricesAndCullingPrimitives(
      int activeLightIndex,
      CubemapFace cubemapFace,
      float fovBias,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData)
    {
      this.Validate();
      return CullingResults.ComputePointShadowMatricesAndCullingPrimitives(this.ptr, activeLightIndex, cubemapFace, fovBias, out viewMatrix, out projMatrix, out shadowSplitData);
    }

    public bool ComputeDirectionalShadowMatricesAndCullingPrimitives(
      int activeLightIndex,
      int splitIndex,
      int splitCount,
      Vector3 splitRatio,
      int shadowResolution,
      float shadowNearPlaneOffset,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData)
    {
      this.Validate();
      return CullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(this.ptr, activeLightIndex, splitIndex, splitCount, splitRatio, shadowResolution, shadowNearPlaneOffset, out viewMatrix, out projMatrix, out shadowSplitData);
    }

    [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
    internal void Validate()
    {
      if (this.ptr == IntPtr.Zero)
        throw new InvalidOperationException("The CullingResults instance is invalid. This can happen if you construct an instance using the default constructor.");
      try
      {
        AtomicSafetyHandle.CheckExistsAndThrow(in this.m_Safety);
      }
      catch (Exception ex)
      {
        throw new InvalidOperationException("The CullingResults instance is no longer valid. This can happen if you re-use it across multiple frames.", ex);
      }
    }

    public unsafe bool Equals(CullingResults other)
    {
      return this.ptr.Equals((object) other.ptr) && this.m_AllocationInfo == other.m_AllocationInfo;
    }

    public override bool Equals(object obj)
    {
      return obj != null && obj is CullingResults other && this.Equals(other);
    }

    public override unsafe int GetHashCode()
    {
      return this.ptr.GetHashCode() * 397 ^ (int) this.m_AllocationInfo;
    }

    public static bool operator ==(CullingResults left, CullingResults right) => left.Equals(right);

    public static bool operator !=(CullingResults left, CullingResults right)
    {
      return !left.Equals(right);
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool ComputeDirectionalShadowMatricesAndCullingPrimitives_Injected(
      IntPtr cullingResultsPtr,
      int activeLightIndex,
      int splitIndex,
      int splitCount,
      ref Vector3 splitRatio,
      int shadowResolution,
      float shadowNearPlaneOffset,
      out Matrix4x4 viewMatrix,
      out Matrix4x4 projMatrix,
      out ShadowSplitData shadowSplitData);
  }
}
